/*
 * 版权所有 (C) 2015 知启蒙(ZHIQIM) 保留所有权利。[遇见知启蒙，邂逅框架梦]
 * 
 * https://zhiqim.org/project/zhiqim_framework/zhiqim_kernel.htm
 *
 * Zhiqim Kernel is licensed under Mulan PSL v2.
 * You can use this software according to the terms and conditions of the Mulan PSL v2.
 * You may obtain a copy of Mulan PSL v2 at:
 *          http://license.coscl.org.cn/MulanPSL2
 * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
 * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
 * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
 * See the Mulan PSL v2 for more details.
 */
package org.zhiqim.kernel.json;

import java.util.ArrayList;
import java.util.List;

import org.zhiqim.kernel.annotation.AnAlias;
import org.zhiqim.kernel.constants.AsciiConstants;
import org.zhiqim.kernel.model.maps.HashMapSO;
import org.zhiqim.kernel.model.maps.HashMapSS;
import org.zhiqim.kernel.model.maps.HashMapSV;
import org.zhiqim.kernel.model.maps.LinkedMapSO;
import org.zhiqim.kernel.model.maps.MapSO;
import org.zhiqim.kernel.model.maps.MapSV;
import org.zhiqim.kernel.util.Classes;
import org.zhiqim.kernel.util.Stringx;
import org.zhiqim.kernel.util.Validates;

/**
 * JSON相关工具类
 *
 * @version v1.0.0 @author zouzhigang 2014-2-27 新建与整理
 */
@AnAlias("Jsons")
public class Jsons implements AsciiConstants
{
    /********************************************************/
    //提供静态的toString和toObject方法,取标准JSON参数
    /********************************************************/
    
    /**
     * 为默认的JSON增加解析器
     * 
     * @param cls    解析类
     * @param parser 解析器
     */
    public static void putParser(Class<?> cls, JsonParser parser)
    {
        Json.json.putParser(cls, parser);
    }
    
    /**
     * 默认的对象转JSON字符串方法，不同的参数请单独使用Json类
     * 
     * @param obj   对象
     * @return      返回JSON字符串
     */
    public static String toString(Object obj)
    {
        return Json.json.toString(obj);
    }
    
    /**
     * 默认的JSON字符串转换成对象，不同的参数请单独使用Json类
     * 
     * @param json  JSON字符串
     * @param cls   转换成对象的类
     * @return      对应的对象
     */
    public static <T> T toObject(String json, Class<T> cls)
    {
        return Json.json.toObject(json, cls, true);
    }
    
    /********************************************************/
    //以下根据toObject和toString的变化
    /********************************************************/
    
    /**
     * 未提供泛型，得到值为基本类型的HashMapSO，如果值是对象如显示为对象的JSON字符串，基本类型转为boolean,long和double三种
     * 
     * @param json  JSON字符串
     * @return      HashMapSO
     */
    public static HashMapSO toMapSO(String json)
    {
        return Json.json.toObject(json, HashMapSO.class, true);
    }
    
    /**
     * 未提供泛型，得到值为基本类型的HashMapSS，如果值是对象如显示为对象的JSON字符串
     * 
     * @param json  JSON字符串
     * @return      HashMapSS
     */
    public static HashMapSS toMapSS(String json)
    {
        return Json.json.toObject(json, HashMapSS.class, true);
    }
    
    /**
     * 得到字符串封装表，字符串可能是[],{}或字符串三种
     * 
     * @param json  JSON字符串
     * @return      HashMapSV<JsonString>
     */
    public static HashMapSV<JsonString> toMapJsonString(String json)
    {
        return toMapSV(json, JsonString.class);
    }
    
    /**
     * 提供泛型，得到值为对象的哈唏表
     * 
     * @param json          JSON字符串
     * @param genericsClass 泛型
     * @return              HashMapSV<V>
     */
    public static <V> HashMapSV<V> toMapSV(String json, Class<V> genericsClass)
    {
        List<String> list = toListByObject(json);
        
        HashMapSV<V> map = new HashMapSV<>();
        for (String s : list)
        {
            int ind = s.indexOf(":");
            String key = removeStartEndQuotation(s.substring(0, ind));
            String value = s.substring(ind+1);
            if ("null".equals(value))
                map.put(key, null);
            else
                map.put(key, toObject(value, genericsClass));
        }
        return map;
    }
    
    /**
     * 提供泛型，得到值为对象的哈唏表
     * 
     * @param json          JSON字符串
     * @param genericsClass 泛型
     * @return              HashMapSV<V>
     */
    public static <V> MapSV<V> toMapSV(String json, Class<?> mapClass, Class<V> genericsClass)
    {
        List<String> list = toListByObject(json);
        
        MapSV<V> map = Classes.newMapSV(mapClass, genericsClass);
        for (String s : list)
        {
            int ind = s.indexOf(":");
            String key = removeStartEndQuotation(s.substring(0, ind));
            String value = s.substring(ind+1);
            if ("null".equals(value))
                map.put(key, null);
            else
                map.put(key, toObject(value, genericsClass));
        }
        return map;
    }
    
    /**
     * 提供泛型，得到列表
     * 
     * @param json          JSON字符串
     * @param genericsClass 泛型
     * @return              List<T>
     */
    public static <T> List<T> toList(String json, Class<T> genericsClass)
    {
        List<String> list = toListByArray(json);
        
        List<T> rst = new ArrayList<T>(list.size());
        for (String s : list)
        {
            rst.add(toObject(s, genericsClass));
        }
        return rst;
    }
    
    /**
     * 提供泛型，得到列表
     * 
     * @param json          JSON字符串
     * @param listClass     列表类
     * @param genericsClass 泛型类
     * @return              List<T>
     */
    public static <T> List<T> toList(String json, Class<?> listClass, Class<T> genericsClass)
    {
        List<String> list = toListByArray(json);
        
        List<T> rst = Classes.newList(listClass, genericsClass);
        for (String s : list)
        {
            rst.add(toObject(s, genericsClass));
        }
        return rst;
    }
    
    /** 提供两个键值生成JSON字符串，对应MAP的一次put */
    public static String toString(String key, Object value)
    {
        MapSO map = new HashMapSO(1);
        map.put(key, value);
        return toString(map);
    }
    
    /** 提供两个键值生成JSON字符串，对应MAP的两次put  */
    public static String toString(String key, Object value, String key2, Object value2)
    {
        MapSO map = new LinkedMapSO(2);
        map.put(key, value);
        map.put(key2, value2);
        return toString(map);
    }
    
    /** 从一个对象或MAP的json中增加或更新指定的一个KEY */
    public static String toStringAddOrUpdate(String json, String key, Object value)
    {
        MapSO map = null;
        if (Validates.isEmpty(json))
            map = new HashMapSO();
        else
            map = toMapSO(json);
        map.put(key, value);
        
        return toString(map);
    }
    
    /** 从一个对象或MAP的json中删除指定的一个KEY */
    public static String toStringRemove(String json, String key)
    {
        if (Validates.isEmpty(json))
            return json;
        
        MapSO map = toMapSO(json);
        map.remove(key);
        
        return toString(map);
    }
    
    /********************************************************/
    //以下解析JSON时对转义符的判断增加和删除
    /********************************************************/
    
    /** 判断是否是不支持的字符（参考Gson不排除/\=#四个） */
    public static boolean isNoSupportChar(char c)
    {
        return (c == '\\' || c == '=' || c == '#');//TODO 1.5.2版本暂时支持 c == '/'，因为Timer用到了
    }
    
    /** 
     * 转义符一共支持10个：
     * 1、顺反斜杠
     * 2、单双引号
     * 3、回车换行，水平垂直制表符和退格符
     * 4、Unicode中的\\u
     */
    public static boolean isEscapeChar(char c)
    {
        return (c == '\\' || c == '/' ||
                 c == '\"' || c == '\'' || 
                 c == 'n'  || c == 'r' || c == 't' || c == 'b' || c == 'f' ||
                 c == 'u');
    }
    

    /**
     * 增加JSON中的转义字符，使用双引号时，单引号不转义，使用单引号时双引号不转义，不使用引号时都转义
     * 
     * @param str       原字符串
     * @param quotation 使用的引号 =0表示未使用,='表示单引号,="表示双引号
     * @return          对字符中需要转义的字符，增加转义符
     */
    public static String addEscapeChar(String str, char quotation)
    {
        if (str == null)
            return null;
        
        StringBuilder strb = new StringBuilder();
        for(int i=0;i<str.length();i++)
        {
            char c = str.charAt(i);
            switch (c)
            {
            case '\\':strb.append("\\\\");break;
            case '/':strb.append("\\/");break;
            case '\"':if (quotation == 0 || quotation == '\"')strb.append("\\\"");else strb.append(c);break;
            case '\'':if (quotation == 0 || quotation == '\'')strb.append("\\\'");else strb.append(c);break;//单引号或无引号时单引号要转义，双引号下的单引号无需处理
            case '\r':strb.append("\\r");break;
            case '\n':strb.append("\\n");break;
            case '\t':strb.append("\\t");break;
            case '\f':strb.append("\\f");break;
            case '\b':strb.append("\\b");break;
            default:strb.append(c);break;
            }
        }

        return strb.toString();
    }
    
    /***
     * 去除JSON中的转义字符
     * 
     * @param str   原字符串
     * @return      去除成对引号之后的字符串
     */
    public static String removeEscapeChar(String str)
    {
        if (str == null)
            return null;
        
        boolean isEscape = false;//是否前一字符是转义字符
        StringBuilder strb = new StringBuilder();
        for(int i=0;i<str.length();i++)
        {
            char c = str.charAt(i);
            if (!isEscape)
            {//未转义
                if (c == '\\')
                    isEscape = true;//设为有转义
                else
                    strb.append(c);
            }
            else
            {//有转义
                switch (c)
                {
                case '\\':strb.append('\\');break;
                case '/':strb.append('/');break;
                case '\"':strb.append('\"');break;
                case '\'':strb.append('\'');break;
                case 'r':strb.append('\r');break;
                case 'n':strb.append('\n');break;
                case 't':strb.append('\t');break;
                case 'f':strb.append('\f');break;
                case 'b':strb.append('\b');break;
                default:strb.append("\\").append(c);break;//如果未找到匹配,则返原值
                }
                isEscape = false;//重置转义为结束
            }
        }
        
        if (isEscape)
        {//最后一个字符是\
            strb.append("\\");
        }
        
        return strb.toString();
    }
    
    /********************************************************/
    //以下解析JSON时需要的字符串分析方法
    /********************************************************/
    
    /** 判断字符串是否是由引号包括，以判断是否是一个指定的字符串 */
    public static boolean isStartEndQuotation(String json)
    {
        if (json == null)
            return false;
        
        if (json.startsWith("\""))
        {//有左侧双引号的，必须右侧双引号，否则抛异常
            if (!json.endsWith("\""))
                throw new JsonException("JSON字符串左侧有双引号时，要求右侧必须有双引号对应");
            
            return true;
        }
        
        if (json.startsWith("\'"))
        {//有左侧单引号的，必须右侧单引号，否则抛异常
            if (!json.endsWith("\'"))
                throw new JsonException("JSON字符串左侧有单引号时，要求右侧必须有单引号对应");
            
            return true;
        }
        
        return false;
    }
    
    /***
     * 去除JSON键和值的前后成对引号
     * 
     * @param json  原字符串
     * @return      去除成对引号之后的字符串
     */
    public static String removeStartEndQuotation(String json)
    {
        if (json == null)
            return null;
        
        if (json.startsWith("\""))
        {//有左侧双引号的，必须右侧双引号，否则抛异常
            if (!json.endsWith("\""))
                throw new JsonException("JSON字符串左侧有双引号时，要求右侧必须有双引号对应");
            
            json = json.substring(1, json.length()-1);
            return json;
        }
        
        if (json.startsWith("\'"))
        {//有左侧单引号的，必须右侧单引号，否则抛异常
            if (!json.endsWith("\'"))
                throw new JsonException("JSON字符串左侧有单引号时，要求右侧必须有单引号对应");
            
            json = json.substring(1, json.length()-1);
            return json;
        }
        
        return json;
    }
    
    /** 去除JSON的空字符串，包括空格,\t,\r,\n */
    public static String removeBlankSpace(String json)
    {
        if (json == null) 
            return null;
        
        json = Stringx.trim(json);
        if (!json.startsWith("{") && !json.startsWith("["))
        {//去掉左右空格，不是对象和数组的，直接返回，中间的空格不处理
            return json;
        }
        
        JsonFlag flag = new JsonFlag();
        StringBuilder strb = new StringBuilder();
        for (int i=0;i<json.length();i++)
        {
            char c = json.charAt(i);
            if (flag.isEscape())
            {//1.在有引号字符串的转义符中
                if (!isEscapeChar(c))
                {//1.1不支持的转义符抛异常
                    throw new JsonException("Json[有引号字符串]中转义符仅支持[r|n|t|b|f|u|\"|\'|\\|/]");
                }
                
                //1.2正常的转义符，置转义结束
                flag.setEscape(false);
                strb.append(c);
            }
            else if (flag.isString())
            {//2.在有引号字符串中
                if (c == _BACK_SLASH_)
                {//2.1遇到反斜杠，置转义开始
                    flag.setEscape(true);
                }
                else if (c == flag.getQuotation())
                {//2.2遇到和开始引号相同的引号，置字符串结束
                    flag.setString(false);
                    flag.setQuotation((char)0);
                }
                
                strb.append(c);
            }
            else if (flag.isStringNoQuotation())
            {//3.在无引号字符串中
                if (isNoSupportChar(c))
                {//3.1无引号字符串不支持的四个字符
                    throw new JsonException("Json[无引号字符串]中不支持[/\\\\=#]四个字符");
                }
                else if (c < _SPACE_)
                {//3.2无引号字符串不支持空格以下空白符
                    throw new JsonException("Json[无引号字符串]中不支持空格以下的空白符，如\\r\\n\\t\\f等");
                }
                else if (c == _SPACE_)
                {//3.3空格要记录，防止空格后面不是JSON分隔符
                    flag.setSpace(true);
                }
                else if (c == ':' || c == ',' || c == '[' || c == ']' || c == '{' || c == '}')
                {//3.4分隔符表示无引号字符串结束
                    flag.setSpace(false);
                    flag.setStringNoQuotation(false);
                    strb.append(c);
                }
                else if (flag.hasSpace())
                {//3.5不是分隔符且前面有空格的，抛异常
                    throw new JsonException("Json[无引号字符串]中间不允许出现空格");
                }
                else
                {//3.6连着的正常字符
                    strb.append(c);
                }
            }
            else
            {//4.不在字符串中，则后面只能出现空白字符或分隔符
                if (c == ':' || c == ',' || c == '[' || c == ']' || c == '{' || c == '}')
                {//4.1分隔符有效
                    strb.append(c);
                }
                else if (c == '\"' || c == '\'')
                {//4.2标准字符串开始
                    flag.setString(true);
                    flag.setQuotation(c);
                    strb.append(c);
                }
                else if (!Validates.isWhitespace(c))
                {//4.3非空白符，表示无符号字符串开始
                    if (isNoSupportChar(c))
                    {//4.3.1不在字符串时不支持的四个字符开头
                        throw new JsonException("Json[无引号字符串]中不支持[/\\\\=#]四个字符");
                    }
                    
                    //4.3.2有效的无符号字符开始
                    flag.setStringNoQuotation(true);
                    strb.append(c);
                }
            }
        }
        
        if (flag.isString())
        {//有引号字符串未结束
            throw new JsonException("Json[有引号字符串]解析失败，未结束即到尾端");
        }
        else if (flag.isStringNoQuotation())
        {//无引号字符串未结束
            throw new JsonException("Json[无引号字符串]解析失败，未结束即到尾端");
        }
        
        return strb.toString();
    }
    
    
    /********************************************************/
    //以下对数组或对象根据逗号拆分成列表
    //1.toListByArray,  格式如["123","abc"]，转为"123"和"abc"两个字符串的列表
    //2.toListByObject,   格式如{"abc":"123","def":"456"}，转为"abc":"123"和"def":"456"两个字符串的列表
    /********************************************************/
    
    /** 折分成字符串列表 */
    public static List<String> toListByArray(String json)
    {
        if (!json.startsWith("[") || !json.endsWith("]"))
            throw new JsonException("Json[数组字符串]，要求[]开头和结尾");
        
        //去除[]
        json = json.substring(1, json.length()-1);
        return toListByArrObj(json, true);
    }
    
    /** 折分成字符串数组 */
    public static List<String> toListByObject(String json)
    {
        if (!json.startsWith("{") || !json.endsWith("}"))
            throw new JsonException("Json[对象字符串]，要求{}开头和结尾");
        
        //去除{}
        json = json.substring(1, json.length()-1);
        return Jsons.toListByArrObj(json, false);
    }
    
    /**
     * 获取对象或数组内的字段列表
     * 1.对象格式：{"abc":"a{b}c"},{"abc":"a{b}c","bcd":"bcd"},和{"abc":"{'bcd':'efg','aaa':'bbb'}"}
     * 2.数组格式：[1,2],["1",2],["a{b}c","bcd"],[[1,2],["[","]","}","{"]]
     * 
     * @param str   字符串
     * @return      得到分离成数组列表或对象字段列表
     */
    public static List<String> toListByArrObj(String str, boolean isArray)
    {
        if (Validates.isEmptyBlank(str))
            return new ArrayList<>();
            
        char begin = isArray?'[':'{';
        char end = isArray?']':'}';
        char obegin = isArray?'{':'[';
        char oend = isArray?'}':']';
        
        ArrayList<String> list = new ArrayList<String>();
        
        JsonFlag flag = new JsonFlag();
        StringBuilder strb = new StringBuilder();
        for (int i=0;i<str.length();i++)
        {
            char c = str.charAt(i);
            if (flag.isEscape())
            {//1.在有引号字符串的转义符中
                if (!isEscapeChar(c))
                {//1.1不支持的转义符抛异常
                    throw new JsonException("Json[有引号字符串]中转义符仅支持[r|n|t|b|f|\"|\'|\\|/]");
                }
                
                //1.2正常的转义符，置转义结束
                flag.setEscape(false);
                strb.append(c);
            }
            else if (flag.isString())
            {//2.在有引号字符串中
                if (c == _BACK_SLASH_)
                {//2.1遇到反斜杠，置转义开始
                    flag.setEscape(true);
                }
                else if (c == flag.getQuotation())
                {//2.2遇到和开始引号相同的引号，置字符串结束
                    flag.setString(false);
                    flag.setQuotation((char)0);
                }
                
                strb.append(c);
            }
            else if (c == begin)
            {//3.遇到下一个开始字符，标志+1
                flag.add();
                strb.append(c);
            }
            else if (c == end)
            {//4.遇到下一个结束字符，标志-1
                flag.sub();
                strb.append(c);
            }
            else if (c == obegin)
            {//5.遇到其他开始字符，标志+1
                flag.oadd();
                strb.append(c);
            }
            else if (c == oend)
            {//6.遇到其他结束字符，标志-1
                flag.osub();
                strb.append(c);
            }
            else if (c == ',')
            {//5.遇到字段分隔符
                if (flag.num() > 0 || flag.onum() > 0)
                {//5.1还在该字段中的对象或数组
                    strb.append(c);
                }
                else
                {//5.2前一个字段结束
                    if (strb.length() > 0)
                    {//5.2.1有效内容添加到列表中
                        list.add(strb.toString());
                    }
                    else
                    {//5.2.2空内容判断数组的添加null到列表中，对象的抛异常
                        if (isArray)
                            list.add(null);
                        else
                            throw new JsonException("Json[对象]中不支持空的字段名和值，通常是多了一个逗号导致");
                    }
                        
                    //5.3重置字段对象
                    strb = null;
                    strb = new StringBuilder();
                }
            }
            else if (c == '\"' || c == '\'')
            {//6.标准字符串开始
                flag.setString(true);
                flag.setQuotation(c);
                strb.append(c);
            }
            else
            {//7.正常字符加入
                strb.append(c);
            }
        }
        
        if (flag.isString())
        {//有引号字符串未结束
            throw new JsonException("Json[有引号字符串]解析失败，未结束即到尾端");
        }
        
        //最后一个结束的加上
        if (strb.length() > 0)
        {//有效内容添加到列表中
            list.add(strb.toString());
        }
        else
        {//空内容判断数组的添加null到列表中，对象的抛异常
            if (isArray)
                list.add(null);
            else
                throw new JsonException("Json[对象字符串]中不支持空的字段名和值，通常是多了一个逗号导致");
        }
        
        list.trimToSize();
        return list;
    }
    
    /********************************************************/
    //以下根据field获取json中对应的value的简单解析字符串方法
    //1.getObject,  格式如{"abc":{}}，其中getMap为getMap的变化
    //2.getArray,   格式如{"abc":["1","2"]}，其中getList为getArray的变化
    //3.getString,  格式如{"abc":"def"}，其中getLong,getInt,getBoolean为getString的变化
    /********************************************************/
    
    /**
     * 获取字段对应的数组字符串值，得到结果为[]开头和结束
     * 
     * @param json      JSON字符串
     * @param field     字段名
     * @return          得到的字符串值，[]开头和结束
     */
    public static final String getArray(String json, String field)
    {
        String val = getValue(json, field);
        if (val == null)
        {//1.没找到field的情况
            return null;
        }
        else if("null".equals(val))
        {//2.得到的值为null(无符号值)的情况
            return null;
        }
        else if (!val.startsWith("[") && !val.startsWith("]"))
        {//3.得到的值不是对象类型
            throw new JsonException("Json字符串[数组字符串]要求[]开头和结尾");
        }
        else
        {//4.有效的对象字符串
            return val;
        }
    }
    
    /**
     * 获取字段对应的对象字符串值，得到结果为{}开头和结束
     * 
     * @param json      JSON字符串
     * @param field     字段名
     * @return          得到的字符串值，{}开头和结束
     */
    public static final String getObject(String json, String field)
    {
        String val = getValue(json, field);
        if (val == null)
        {//1.没找到field的情况
            return null;
        }
        else if("null".equals(val))
        {//2.得到的值为null(无符号值)的情况
            return null;
        }
        else if (!val.startsWith("{") && !val.startsWith("}"))
        {//3.得到的值不是对象类型
            throw new JsonException("Json字符串[对象字符串]要求{}开头和结尾");
        }
        else
        {//4.有效的对象字符串
            return val;
        }
    }
    
    /**
     * 获取字段对应的字符串值，支持双引号、单引号和无引号三种字符串值，如果对应的值是{或[开头则认为是对象或数组
     * 
     * @param json      JSON字符串
     * @param field     字段名
     * @return          得到的字符串值
     */
    public static String getString(String json, String field)
    {
        String val = getValue(json, field);
        if (val == null)
        {//1.没找到field的情况
            return null;
        }
        else if("null".equals(val))
        {//2.得到的值为null(无符号值)的情况
            return null;
        }
        else if (val.startsWith("{") || val.startsWith("["))
        {//3.得到的值是数组或对象的情况
            return val;
        }
        else
        {//4.得到的值是字符串情况（有符号字符串，或无符号整型等）要去除前后引号和转义处理
            val = removeStartEndQuotation(val);
            val = removeEscapeChar(val);
            return val;
        }
    }
    
    /** 获取字段对应的数组字符串列表，得到结果折成列表 */
    public static List<String> getList(String json, String field)
    {
        String val = getArray(json, field);
        if (val == null)
            return new ArrayList<>();
            
        val = val.substring(1, val.length()-1);
        return toListByArrObj(val, true);
    }
    
    /** 获取long,如果未取到或不是long，则取缺省值 */
    public static final long getLong(String json, String field, long defaultValue)
    {
        String num = getString(json, field);
        if (!Validates.isInteger(num))
            return defaultValue;
        
        return Long.parseLong(num);
    }
    
    /** 获取long */
    public static final long getLong(String json, String field)
    {
        String num = getString(json, field);
        if (!Validates.isInteger(num))
            return -1;
        
        return Long.parseLong(num);
    }
    
    /** 获取int,如果未取到或不是int，则取缺省值 */
    public static final int getInt(String json, String field, int defaultValue)
    {
        String num = getString(json, field);
        if (!Validates.isInteger(num))
            return defaultValue;
        
        return Integer.parseInt(num);
    }
    
    /** 获取int */
    public static final int getInt(String json, String field)
    {
        String num = getString(json, field);
        if (!Validates.isInteger(num))
            return -1;
        
        return Integer.parseInt(num);
    }
    
    /** 获取boolean */
    public static final boolean getBoolean(String json, String field)
    {
        String str = getString(json, field);
        return "true".equals(str);
    }
    
    /** 获取boolean */
    public static final boolean getBoolean(String json, String field, boolean defaultValue)
    {
        String str = getString(json, field);
        if (str == null)
            return defaultValue;
        
        return "true".equals(str);
    }
    
    /******************************************************************************************/
    //以下根据field获取json中对应的value的简单解析字符串方法
    //1.getValue,                   总方法，获取对象中指定字段的值（数组、对象、有引号字符串和无引号字符串）
    //2.getIndex,                   判断字段是否存在
    //3.getValueArrObj,             对数组和对象进行{}[]配对
    //4.getValueString,             对有引号字符串"",''进行配对
    //5.getValueStringNoQuotation,  对无引号字符串检查到,或}进行配对
    /******************************************************************************************/
    
    /**
     * 通过对象字段获取对应的值，值有三种情况，1）数组，2）对象，3）字符串（有引号的和无引号的null,boolean,int等）
     * 
     * @param json      JSON字符串
     * @param field     字段名
     * @return          值有三种情况，1）数组，2）对象，3）字符串（有引号的和无引号的null,boolean,int等）
     */
    private static String getValue(String json, String field)
    {
        if (json == null || field == null)
            return null;
        
        //1.先删除空白
        json = removeBlankSpace(json);
        
        //2.并找到字段所在
        int ind = getIndex(json, field);
        if (ind == -1)
        {//未找到字段的情况
            return null;
        }
        
        //3.取值的第一个字符，判断类型
        char first = json.charAt(ind);
        StringBuilder strb = new StringBuilder();
        strb.append(first);

        JsonFlag flag = new JsonFlag();
        if (first == '[' || first == '{')
        {//3.1对象或数组
            flag.add();
            return getValueArrObj(json, strb, flag, ind, first == '[');
        }
        else if (first == '\"' || first == '\'')
        {//3.2有引号字符串
            flag.setString(true);
            flag.setQuotation(first);
            return getValueString(json, strb, flag, ind);
        }
        else
        {//3.3无符号字符串
            flag.setStringNoQuotation(true);
            return getValueStringNoQuotation(json, strb, flag, ind);
        }
    }
    
    /** 获取字段对应的值起始索引值 */
    private static int getIndex(String json, String field)
    {
        int fieldLen = field.length();
        
        //先判断双引号情况
        int ind = json.indexOf("\""+field+"\":");
        if (ind != -1)
            return ind + 1 + fieldLen + 1 + 1;//"field":
        
        //再判断无引号情况
        ind = json.indexOf(field+":");
        if (ind != -1)
            return ind + fieldLen + 1;//field:
        
        //最后判断单引号情况
        ind = json.indexOf("\'"+field+"\':");
        if (ind != -1)
            return ind + 1 + fieldLen + 1 + 1;//'field':
        
        return -1;
    }
    
    /** 读取字段对应的值[数组或对象] */
    private static String getValueArrObj(String json, StringBuilder strb, JsonFlag flag, int ind, boolean isArray)
    {
        char begin = isArray?'[':'{';
        char end = isArray?']':'}';
        
        for (int i=(ind+1);i<json.length();i++)
        {
            char c = json.charAt(i);
            if (flag.isEscape())
            {//1.在有引号字符串的转义符中
                if (!isEscapeChar(c))
                {//1.1不支持的转义符抛异常
                    throw new JsonException("Json[有引号字符串]中转义符仅支持[r|n|t|b|f|\"|\'|\\|/]");
                }
                
                //1.2正常的转义符，置转义结束
                flag.setEscape(false);
                strb.append(c);
            }
            else if (flag.isString())
            {//2.在有引号字符串中
                if (c == _BACK_SLASH_)
                {//2.1遇到反斜杠，置转义开始
                    flag.setEscape(true);
                }
                else if (c == flag.getQuotation())
                {//2.2遇到和开始引号相同的引号，置字符串结束
                    flag.setString(false);
                    flag.setQuotation((char)0);
                }
                
                strb.append(c);
            }
            else if (c == begin)
            {//3.遇到下一个开始字符，标志+1
                flag.add();
                strb.append(c);
            }
            else if (c == end)
            {//4.遇到下一个结束字符，标志-1
                flag.sub();
                strb.append(c);
                
                if (flag.num() == 0)
                {//找到对应的结束符
                    return strb.toString();
                }
            }
            else if (c == '\"' || c == '\'')
            {//5.标准字符串开始
                flag.setString(true);
                flag.setQuotation(c);
                strb.append(c);
            }
            else
            {//6.正常字符加入
                strb.append(c);
            }
        }
        
        //最后还未结束的
        throw new JsonException("Json[数组或对象]未找到对应的结束符");
    }
    
    /** 读取字段对应的字符串[有引号] */
    private static String getValueString(String json, StringBuilder strb, JsonFlag flag, int ind)
    {
        for (int i=(ind+1);i<json.length();i++)
        {
            char c = json.charAt(i);
            if (flag.isEscape())
            {//1.在有引号字符串的转义符中
                if (!isEscapeChar(c))
                {//1.1不支持的转义符抛异常
                    throw new JsonException("Json[有引号字符串]中转义符仅支持[r|n|t|b|f|\"|\'|\\|/]");
                }
                
                //1.2正常的转义符，置转义结束
                flag.setEscape(false);
                strb.append(c);
            }
            else
            {//2.在有引号字符串中
                if (c == _BACK_SLASH_)
                {//2.1遇到反斜杠，置转义开始
                    flag.setEscape(true);
                }
                else if (c == flag.getQuotation())
                {//2.2遇到和开始引号相同的引号，置字符串结束
                    strb.append(c);
                    return strb.toString();
                }
                
                strb.append(c);
            }
        }
        
        //最后还未结束的
        throw new JsonException("Json[有引号字符串]未找到对应的结束引号");
    }
    
    /** 读取字段对应的字符串[无引号] */
    private static String getValueStringNoQuotation(String json, StringBuilder strb, JsonFlag flag, int ind)
    {
        for (int i=(ind+1);i<json.length();i++)
        {
            char c = json.charAt(i);
            if (isNoSupportChar(c) || c == ':' || c == '[' || c == ']' || c == '{')
            {//1.无引号字符串不支持的四个字符和JSON定义符
                throw new JsonException("Json[无引号字符串]中不支持[/\\\\=#]四个字符，值中不支持:[]{四个字符");
            }
            else if (c < _SPACE_)
            {//2.无引号字符串不支持空格以下空白符
                throw new JsonException("Json[无引号字符串]中不支持空格以下的空白符，如\\r\\n\\t\\f等");
            }
            else if (c == _SPACE_)
            {//3.空格要记录，防止空格后面不是JSON分隔符
                flag.setSpace(true);
            }
            else if (c == ',' || c == '}')
            {//4.分隔符表示无引号字符串结束
                return strb.toString();
            }
            else if (flag.hasSpace())
            {//5.不是分隔符且前面有空格的，抛异常
                throw new JsonException("Json[无引号字符串]中间不允许出现空格");
            }
            else
            {//6.连着的正常字符
                strb.append(c);
            }
        }
        
        //最后还未结束的
        throw new JsonException("Json[无引号字符串]未找到对应的结束符[}或,]字符");
    }
}
